﻿using System;
using GiteeApi.Dtos;
using GiteeApi.Models;
using GiteeApi.Services;
using GiteeApi.Utils;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using System.Threading.Tasks;
using AutoMapper;
using Microsoft.AspNetCore.Authorization;

namespace GiteeApi.Controllers
{
    /// <summary>
    /// 用户操作
    /// </summary>
    [Route("api/[controller]/[action]")]
    [ApiController]
    public class UserController : ControllerBase
    {
        /// <summary>
        /// 配置
        /// </summary>
        private IConfiguration _configuration;

        /// <summary>
        /// Services
        /// </summary>
        private UserServices _userServices;

        /// <summary>
        /// 映射
        /// </summary>
        private IMapper _mapper;

        /// <summary>
        /// 邮箱
        /// </summary>
        private EmailUtil _emailUtil;

        /// <summary>
        /// Redis
        /// </summary>
        private RedisCacheHelper _redisCacheHelper;

        /// <summary>
        /// JWT
        /// </summary>
        private JWTUtil _jwt;

        /// <summary>
        /// 构造器
        /// </summary>
        /// <param name="userServices"></param>
        /// <param name="configuration"></param>
        /// <param name="mapper"></param>
        public UserController(UserServices userServices, IConfiguration configuration, IMapper mapper,
            EmailUtil emailUtil, RedisCacheHelper redisCacheHelper, JWTUtil jwt)
        {
            _userServices = userServices;
            _configuration = configuration;
            _mapper = mapper;
            _emailUtil = emailUtil;
            _redisCacheHelper = redisCacheHelper;
            _jwt = jwt;
        }

        /// <summary>
        /// 登陆
        /// </summary>
        /// <param name="loginDto">邮箱；密码</param>
        /// <returns>登陆结果</returns>
        [HttpPost]
        public async Task<IActionResult> Login(LoginDto loginDto)
        {
            // MD5
            loginDto.Password = MD5Util.Get(loginDto.Password);

            // 账号密码是否正确
            var result = await _userServices.LoginAsync(loginDto);
            if (result is null)
            {
                return Ok(new RequestBack(0, "账号或密码错误！"));
            }
            
            // 是否被封禁
            if (result.Delete == 1)
            {
                return Ok(new RequestBack(0, "此账号已被移除！"));
            }

            // 映射
            var userInfoDto = _mapper.Map<UserInfoDto>(result);

            // 生成 Token
            userInfoDto.Token = _jwt.GetToken(result.Id);

            // 返回对应用户信息
            return Ok(new RequestBack(1, "登陆成功！", userInfoDto));
        }

        /// <summary>
        /// 注册获取邮箱验证码
        /// </summary>
        /// <param name="mailDto">邮箱</param>
        /// <returns>是否发送成功</returns>
        [HttpPost]
        public async Task<IActionResult> GetRegisterMailCode(MailDto mailDto)
        {
            return await SendCodeMail(mailDto.mail, 6, "您的注册验证码为：{0}，五分钟内有效！", "reg", true);
        }

        /// <summary>
        /// 发送各类邮件
        /// </summary>
        /// <param name="mail">邮箱</param>
        /// <param name="codeLength">随机码长度</param>
        /// <param name="msg">内容</param>
        /// <param name="redis">redis存储前缀</param>
        /// <param name="CheckEmail">是否检查邮箱注册情况</param>
        /// <returns></returns>
        private async Task<IActionResult> SendCodeMail(string mail, int codeLength, string msg, string redis, bool CheckEmail)
        {
            // 数据验证
            if (string.IsNullOrEmpty(mail))
            {
                return Ok(new RequestBack(0, "邮箱不能为空！"));
            }

            // 是否被注册
            if (CheckEmail && await _userServices.CheckEmailExistAsync(mail))
            {
                return Ok(new RequestBack(0, "该邮箱已被注册！"));
            }

            // 生成验证码
            var code = RandomCode.Create(codeLength).ToLower();

            // 存入 Redis
            if (!_redisCacheHelper.Set($"{redis}_{mail}", code, new TimeSpan(0, 5, 0)))
            {
                return Ok(new RequestBack(0, "Redis出现了错误！"));
            }

            // 发送邮件
            await _emailUtil.SendMail(mail, "N0ts Gitee API Server", string.Format(msg, code));

            return Ok(new RequestBack(1, "发送成功"));
        }

        /// <summary>
        /// 注册
        /// </summary>
        /// <param name="registerDto">邮箱验证码；邮箱；密码；确认密码</param>
        /// <returns>注册结果</returns>
        [HttpPost]
        public async Task<IActionResult> Register(RegisterDto registerDto)
        {
            // 验证码是否正确
            var codeCache = _redisCacheHelper.Get($"reg_{registerDto.Email}");
            if (codeCache != registerDto.MailCode)
            {
                return Ok(new RequestBack(0, "验证码错误！"));
            }

            // 删除 Redis
            _redisCacheHelper.Del($"reg_{registerDto.Email}");

            // 是否被注册
            if (await _userServices.CheckEmailExistAsync(registerDto.Email))
            {
                return Ok(new RequestBack(0, "该邮箱已被注册！"));
            }

            // MD5
            registerDto.Password = MD5Util.Get(registerDto.Password);

            // 新增
            if (await _userServices.RegisterAsync(registerDto))
            {
                return Ok(new RequestBack(1, "注册成功"));
            }

            return Ok(new RequestBack(0, "注册失败"));
        }

        /// <summary>
        /// 修改密码
        /// </summary>
        /// <param name="password">密码</param>
        /// <returns>修改结果</returns>
        [HttpPut]
        [Authorize]
        public async Task<IActionResult> ChangePwd(ChangePasswordDto changePasswordDto)
        {
            int userId = Convert.ToInt32(Response.HttpContext.User.Identity.Name);
            var pwdAsync = await _userServices.ChangePwdAsync(userId, changePasswordDto.password);
            if (pwdAsync)
            {
                return Ok(new RequestBack(1, "修改成功"));
            }
            return Ok(new RequestBack(0, "修改失败"));
        }
    }
}